# -*- coding: iso8859 -*-

import sys, logging, time, logging
from StringIO import StringIO
from urllib2 import urlopen, HTTPError, HTTPCookieProcessor, install_opener, build_opener, addinfourl, Request

try:
   from google.appengine.api import urlfetch
   GAE = True
   logging.warn("on GAE, faking urlopen")

   def fakeopen(url):
      if isinstance(url, Request):
         url = url.get_full_url()
      try:
         res_g = urlfetch.fetch(url)
         fp = StringIO(res_g.content)
         return addinfourl(fp, res_g.headers, url)
      except HTTPError, e:
         raise HTTPError(url, 404, "google url fetch failed", {}, StringIO())
      except urlfetch.DownloadError, e:
         logging.error("error fetching %s: %s" % (url, e))

   urlopen = fakeopen
   logging.warn("urlopen: %s" % str(urlopen))

except ImportError, e:
   GAE = False
   logging.warn("not on GAE")

from cookielib import CookieJar
from ClientForm import ParseResponse
from BeautifulSoup import BeautifulSoup

wilimaurl = "http://lprwilima.amec.fi/traveller/matkainfo"

wilimans = "http://lprwilima.lappeenranta.fi/busstops/2006/11"

__all__ = ("getBusStops", "getDepartures", "wilimans", "wilimaurl")

def install_cookieopener():
   # Install opener that handles cookies
   cj = CookieJar()
   processor = HTTPCookieProcessor(cj)
   install_opener(build_opener(processor))


def getServiceForm(url=wilimaurl):
   try:
      response = urlopen(url)
   except HTTPError, response:
      raise Exception("Could not retrieve bus service URL", response)
   forms = ParseResponse(response, backwards_compat=False)
   return forms[0]


def cleanUpStopName(label):
   label = label.replace("Lsala", "Lauritsala")
   data = label.split("(")
   if len(data) > 1:
      mainname = data[0].strip()
      qualifier = data[1].strip()[:-1].rstrip()
      label = "%s (%s)" % (mainname, qualifier)

   return label


def parseDepartureResultsView(response):
   "return [(lineno, linename), (leaves_from, travelday, leaves_at), (arrives_to, arrival_day, arrives_at)]"

   departurespage = response.read()
   del response
   soup = BeautifulSoup(departurespage)
   table = soup("table",{"width":"630", "cellspacing":"1"})[0]
   departures = []
   for trow in table(lambda(x):x.name=="tr" and len(x)>3)[1:]:
      lineno = trow.td.font.a.string.strip()
      linename, departure, arrival, comment = trow("td",{"height":"21"})
      linename = linename.font.string.strip()
      departure = departure.font.strong.string.strip()
      travelday, leaves_at = departure.split()[:2]
      leaves_from = " ".join(departure.split()[2:])

      arrival = arrival.font.strong.string.strip()
      arrives_at = arrival.split()[0]
      arrives_to = " ".join(arrival.split()[1:])

      departure = (
         (lineno, linename),
         (cleanUpStopName(leaves_from), travelday, leaves_at),
         (cleanUpStopName(arrives_to), arrives_at)
      )
      departures.append(departure)

   return departures


def getBusStops(url=wilimaurl):
   "return all bus stops as a (name:value) dict"
   form = getServiceForm()
   try:
      # we assume all stops are used for both departure and arrival
      stops_source = form.find_control("lahtopaikka")
   except:
      raise Exception("no stop source element found")

   # decode UTF-8 from BeautifulSoup
   stops = [(unicode(stop.name), cleanUpStopName(stop.attrs["label"].decode("utf-8"))) for stop in stops_source.items]
   return stops #print type(stops_source.items[0].attrs["label"])


def getDepartures(stop_from, stop_to, departure_time=None, departures=3):
   "get next departures"

   if not departure_time:
      # hardcode to gmt + 2
      gm = list(time.gmtime())
      gm[3] = gm[3] + 2
      departure_time = gm[:5]

   year, month, day, hour, minute = [t for t in departure_time]

   form = getServiceForm()
   form.find_control("lahtopaikka").get(stop_from).selected=True
   form.find_control("maarapaikka").get(stop_to).selected=True
   form["vuosi"] = str(year)
   form["kuukausi"] = str(month)
   form["paiva"] = str(day)
   form["tunnit"] = str(hour)
   form["minuutit"] = str(minute)

   # not being used right now - how can I set a hidden form field?
   #form["maxtuloksia"] = str(departures)

   submit = form.find_control("submit")
   form.method = "GET"
   request = form.click()

   try:
       response = urlopen(request)
       del request
   except HTTPError, response2:
      raise Exception("Could not get timetables", response)

   return parseDepartureResultsView(response)


if __name__=="__main__":

   print getBusStops()

   for s in getBusStops():
      print s[0], s[1]

   stop_from = ("PA1023","Kivisalmi (Kivistönkatu)")
   stop_to = ("PA100","KESKUSTA (Koulukatu)")

   departures = getDepartures(stop_from=stop_from[0], stop_to=stop_to[0])
   print departures
   for  iline, ifrom, ito in departures:
      print "-------------------------"
      print "line: %s - %s" % iline
      print "from %s departs at %s" % ((ifrom[0], ifrom[2]))
      print "to %s - arrives at %s" % (ito[0:2])

